import React, {
  forwardRef,
  ReactNode,
  ReactText,
  Ref,
  useEffect,
  useImperativeHandle,
  useState,
  useRef,
  useMemo,
} from 'react';
import { connect, mapProps } from '@formily/react';
import { getMessage, TextWidget } from '@inbiz/react';
import { Divider, Spin } from 'antd';
import { useRequest } from 'ahooks';
import classNames from 'classnames';
import { CaretRightOutlined } from '@ant-design/icons';
import { useEvents, combineResultId, getCookie } from '@inbiz/utils';
import { IValue as IConfigModalValue } from '../../designer/components/configModal';
import { IValue as IBusinessData } from '../../designer/components/subtableConfigModal';
import MultipleView from './components/multipleView';
import SingleView from './components/singleView';
import api from './api';
import { getDocumentInfo, apiWrapper, getData, getPathName } from './service';
import { IOptionType } from './type';
import './style.less';

const sep = '$__split__$';

const formatResult = (data: any[], isChild = false) => {
  return (data || []).map((item: any) => ({
    ...item,
    isLeaf: isChild ? false : (item.child?.length ?? 0) === 0, // 强制所有节点可以展开；本来说好的判断是否还有 child 来判断是否有下级，接口问题
    hasAsked: !isChild,
    child: item.child ? formatResult(item.child as Array<any>, true) : undefined, // 只需要 isLeaf 来控制，去掉多余的 child
  }));
};

const formatKey = (value: Array<string>, multiple: boolean) => {
  if (multiple) {
    const len = value?.length ?? 0;
    if (len > 0) {
      const result = value.map((ele) => {
        const _len = ele.length;
        return ele[_len - 1];
      });
      return result?.join?.(sep);
    }
    return 'vKey';
  }
  return value?.join?.(sep) || 'vKey';
};
export interface CascaderProps {
  /**
   * @description 设置统一样式前缀。注意：需要配合 less 变量 @inbiz-prefix 使用
   * @default     inbiz
   */
  prefixCls?: string;
  /**
   *  @description 自定义类名
   */
  className?: string;
  /**
   * @description 自定义样式
   */
  style?: React.CSSProperties;
  /**
   * @description 输入框占位文本
   * @default     请选择
   */
  placeholder?: string;
  /**
   * @description 只读
   * @default     false
   */
  readOnly?: boolean;
  /**
   * @description 禁用
   * @default     false
   */
  disabled?: boolean;
  /**
   * @description 支持多选节点
   * @default     false
   */
  multiple: boolean;
  /**
   * @description 支持多选节点
   * @default     false
   */
  showCheckedStrategy: 'SHOW_PARENT' | 'SHOW_CHILD';
  /**
   * @description 选取规则
   * @default    SHOW_PARENT
   */
  storageMode?: 'model' | 'submodel';
  /**
   * @description 指定选中项
   */
  value?: ReactText[];
  /**
   * @description 选取中间项/最后一级
   * @default    leaf
   */
  targetLevel?: 'any' | 'leaf';
  /**
   * @description 自定义配置相关参数
   */
  configModalValue?: IConfigModalValue;
  /**
   * @description 子表存储相关参数
   */
  businessData?: IBusinessData;
  /**
   * @description 子表存储相关参数
   */
  storageConfig?: {
    business: string;
    tableData: {
      componentAttr: string;
      modelAttr: string;
    }[];

    configModalValue?: any;
  };
  /**
   * @description 控件id
   */
  controlId: string;
  /**
   * @description 子表存储
   */
  childModelConfig?: boolean;
  /**
  // /**
  //  * @description 修改的控件的id
  //  */
  originValue: ReactText[];

  // 查看模式
  viewMode?: string;

  primarykey?: any;
  /**
   * @description 获取子表存储相关参数
   */
  getBusinessData?: (v?: IBusinessData) => void;
  /**
   * @description 选择完成后的回调
   */
  onChange?: (v: ReactText[]) => void;
  sourceModel?: string;
  modelkey?: string;
  inbiz?: any;
  callBackEvents?: {
    onParamFormat?: <T>(param: T) => T;
    onRequest?: (param: Parameters<typeof getData>[number]) => Promise<object>;
    onData?: <T>(data: T) => T;
    onTextParamFormat?: <T>(param: T) => T;
    onTextRequest?: (param: Parameters<typeof getPathName>[number]) => Promise<object>;
    onTextData?: <T>(data: T) => T;
  };
  emit?: {
    (type: 'onload'): void;
    (type: 'onSuccess', arg: IOptionType[]): void;
    (type: 'onError'): void;
    (type: 'onDropdownVisibleChange', arg: boolean): void;
    (type: 'onSelect', arg: ReactText[], arg1: IOptionType[]): void;
  };
}

type IRef = Ref<ReturnType<typeof api>>;
export interface Array<T> {

}

const Cascader: EFC<CascaderProps, any> = forwardRef((props: CascaderProps, ref: IRef) => {
  const {
    storageMode,
    prefixCls = 'inbiz',
    className,
    disabled,
    readOnly,
    value: propsValue = [],
    // value = ['3', '1-1-1', '1-1-2-1'], // 多选
    // value = ['1-1-2-1'], // 单选
    style,
    placeholder,
    multiple,
    configModalValue,
    modelkey,
    primarykey,
    businessData,
    targetLevel,
    sourceModel,
    inbiz,
    callBackEvents,
    showCheckedStrategy,
    viewMode,
    emit,
    getBusinessData,
    onChange,
    ...restProps
  } = props;
  const value = propsValue || [];
  const vKey = formatKey(value, multiple);
  const [configEvents] = useEvents(callBackEvents, emit);
  const [options, setOptions] = useState<IOptionType[]>([]);
  const [stateValue, setStateValue] = useState<{ [p: string]: ReactText[] | ReactText[][] }>({}); // 组件内部真实值，多选为二维数组，做缓存防止每次改变都请求接口获取完整链路
  const [labelMap, setLabelMap] = useState<{ [p: string]: string[] }>({}); // 组件内部回显时需要用到的显示值
  const [load, setLoad] = useState(false);
  const [firstGetTree, setFirstGetTree] = useState(true);
  const parentRef = useRef<HTMLDivElement>();

  const cacheRef = useRef<string>('');

  const isExtendData = useRef(false)
  const reqParams = {
    appId: inbiz?.appInfo.appId,
    id: configModalValue?.currentIdField || '',
    sourceKey: sourceModel || '',
    parentId: configModalValue?.parentIdField || '',
  };
  const fieldNames = {
    label: configModalValue?.labelField || '',
    value: configModalValue?.currentIdField || '',
    children: 'child',
  };

  /**
   * 扩展代码相关包装
   */
  const getDataService = apiWrapper(getData, configEvents, {
    onRequest: 'onRequest',
    onParamFormat: 'onParamFormat',
    onData: 'onData',
  });

  /**
   * 扩展代码相关包装
   */
  const getPathNameService = apiWrapper(getPathName, configEvents, {
    onRequest: 'onTextRequest',
    onParamFormat: 'onTextParamFormat',
    onData: 'onTextData',
  });
  const { run: getTreeAsync, loading: getTreeAsyncLoading } = useRequest(getDataService, {
    manual: true,
    defaultParams: [{ ...reqParams, parentId: reqParams?.parentId.split('$')[0], value: 0 }],
    onSuccess: (resData) => {
      const data = formatResult(resData?.data);
      setOptions(data);
      setFirstGetTree(false);
      if (!load) {
        emit?.('onload');
        setLoad(true);
      }
      emit?.('onSuccess', data);
    },
    onError: () => emit?.('onError'),
  });

  const { run } = useRequest(getPathNameService, {
    manual: true,
    onSuccess: async (pRes) => {
      const res = pRes.map((item: any) => ({
        ...item,
        path: `${item.path}`,
        namepath: item.namepath?.replace('0/1/', '').slice(0, -1) ?? '',
      })); // 接口尾巴上多带了一个 /

      if (props.childModelConfig && props.value && props.value.join(',') !== cacheRef.current) {
        const response = await getDataService({
          ...reqParams,
          parentId: reqParams?.parentId.split('$')[0],
          value: 0,
        });
        setOptions(response.data ?? []);
      }
      const nextValue = res
        .map((item) => {
          setLabelMap((prev) => ({
            ...prev,
            [item[fieldNames.value.split('$')[0]]]: item.namepath.split('/'),
          }));
          return item.path
            .split('/')
            .map((v) => (typeof value[0] === 'number' ? Number(v) : String(v)));
        })
        .filter(Boolean); // 防止接口查询不到数据
      setStateValue({ [vKey]: multiple ? nextValue : nextValue[0] }); // 通过单节点值转为组件可用的链路数组，多选时是二维，单选是一维
    },
  });

  /**
   * 异步加载树形数据，和 antd 保持一致
   * @param selectedOptions
   * @returns
   */
  const loadData = async (selectedOptions: IOptionType[]) => {
    const targetOption = selectedOptions[selectedOptions.length - 1];
    if (targetOption.hasAsked || isExtendData.current) {
      return;
    }
    targetOption.loading = true;
    try {
      const res = await getDataService({
        ...reqParams,
        parentId: reqParams?.parentId.split('$')[0],
        value: targetOption[configModalValue?.currentIdField.split('$')[1] || ''],
      });

      targetOption.loading = false;
      targetOption.hasAsked = true;
      if (res.data.length === 0) {
        targetOption.isLeaf = true;
        targetOption.child = undefined;
      } else {
        targetOption.child = res.data.map((ele: any) => ({
          ...ele,
          isLeaf: false,
          child: null,
          hasAsked: false,
        }));
      }
      // const childExtend =
      //   targetLevel === 'leaf' && res.data.length > 0 ? res.data.concat({}) : res.data; // 如果是叶子节点就加入一个隐藏的空节点，防止下级选完后自动定位上级
      // const nextChildren = formatResult(childExtend);
      // targetOption.child = nextChildren;
      // targetOption.isLeaf = nextChildren.length === 0; // 动态拉取后需要改变是否可以下拉的箭头，接口问题
      setOptions([...options]);
      emit?.('onSuccess', [...options]);
    } catch {
      emit?.('onError');
    }
  };
  /**
   * 多选的改变，需要将二维数组转换成统一的 value
   * @param v
   * @param vOptions
   */
  const multipleChange = (v: ReactText[][], vOptions: IOptionType[]) => {
    const strKey = v
      ?.map((ele) => {
        const len = ele.length;
        const last = ele[len - 1];
        return last;
      })
      .join(sep);
    setStateValue({ [strKey]: v });
    onChange?.(v);
    emit?.('onSelect', v as ReactText[], vOptions);
  };

  /**
   * 单选的改变，需要将一维的链式数据转换成单节点数据，所以回显时就得把单节点数据还原成链式数据
   * @param v
   * @param vOptions
   */
  const singleChange: (v: ReactText[], vOptions: IOptionType[]) => void = (
    v = [],
    vOptions = [],
  ) => {
    // const [nextV, nextVOptions] = [[...v].pop(), [...vOptions].pop()];
    setStateValue({ [[[...v].pop()].join(sep)]: v });
    onChange?.(v ? [...v] : []);
    cacheRef.current = (v ? [...v] : []).join(',');
    emit?.('onSelect', v ? [...v] : [], vOptions ? [...vOptions] : []);
  };

  useImperativeHandle(
    ref,
    () => {
      return {
        ...api(configEvents, {
          fieldNames,
          setOptions:(data: React.SetStateAction<IOptionType[]>) => {
            isExtendData.current = true;
            setOptions(data)
          },
          ...props,
          value,
          options,
        }),
      };
    },
    [value, options, fieldNames, props],
  );
  useEffect(() => {
    if (value.length && !stateValue[vKey] && !isExtendData.current) {
      // 编辑时候的回显数据，需要二次加工（转为完整的二维链路）；因为对外 onChange 抛出的是一维，所以每次都得加工
      run({
        ...reqParams,
        parentId: reqParams?.parentId.split('$')[0],
        sourceType: 1,
        values: value,
        name: configModalValue?.labelField?.split('$')[0] || '',
      });
    } else if (!value.length) {
      setStateValue({ [vKey]: [] });
    }
  }, [JSON.stringify(value)]);

  useEffect(() => {
    if (storageMode === 'submodel' && multiple) {
      getBusinessData?.(businessData);
    }
  }, [businessData, storageMode, multiple]);

  //初始化数据
  useEffect(() => {
    getTreeAsync({ ...reqParams, parentId: reqParams?.parentId.split('$')[0], value: 0 });
  }, []);

  const commonProps = {
    className: classNames(`${prefixCls}-Cascader`, className),
    dropdownClassName: `${prefixCls}-Cascader-dropdown`,
    disabled: disabled || readOnly,
    placeholder: (
      <span style={{ fontSize: 'var(--inbiz-font-size-base)' }}>
        <TextWidget>{placeholder}</TextWidget>
      </span>
    ),
    options,
    style,
    targetLevel,
    fieldNames: {
      ...fieldNames,
      label: fieldNames.label.split('$')[1],
      value: fieldNames.value.split('$')[1],
    },
    labelMap,
    expandIcon: <CaretRightOutlined />,
    showCheckedStrategy,
    loadData,
    onDropdownVisibleChange: (e: boolean) => {
      if (e && firstGetTree) {
        getTreeAsync({ ...reqParams, parentId: reqParams?.parentId.split('$')[0], value: 0 });
      }
      emit?.('onDropdownVisibleChange', e);
    },
    dropdownRender: (menus: ReactNode) => <Spin spinning={getTreeAsyncLoading}>{menus}</Spin>,
    // getPopupContainer: () => parentRef.current,
  };
  const getSingleValue = () => {
    if (vKey !== 'vKey') {
      const result = vKey.split(sep);
      return result;
    }
    return undefined;
  };

  const [text, $text] = useState('')
  useEffect(() => {
    if (!viewMode) return;
    let params = {
      sourceKey: props.sourceModel,
      parentId: configModalValue?.parentIdField?.split('$')[0],
      sourceType: modelkey ? 1 : 'api',
      values: props.value?.slice(-1),
      name: configModalValue?.labelField?.split('$')[0],
      id: configModalValue?.currentIdField || '',
      token: getCookie('token'),
      appId: inbiz?.appInfo.appId
    }
   
    getPathName(params).then((res) => {
      let showValue;

      if(res){
        if (multiple) {
          showValue = res?.map((item: any) => {
            let str = item.namepath.substring(0, item.namepath.length - 1)
            if (str.indexOf('/') != -1) {
              str = str.split('/').slice(-1).toString()
            }
            return str
          }).toString()
  
        } else {
          showValue = res?.map((item: any) => { return item.namepath }).toString()
          showValue = showValue?.substring(0, showValue.length - 1)
        }
        $text(showValue)
      }

     
    })
  }, [viewMode])

  return (
    <div {...restProps} title="" ref={parentRef}>
      {
        multiple ? viewMode == 'look' ? <div>{text}</div> : (
          <MultipleView
            {...commonProps}
            value={stateValue[vKey] as React.ReactText[][]}
            onChange={multipleChange}
          />
        ) : viewMode == 'look' ? <div>{text}</div> :
          (<SingleView {...commonProps} value={getSingleValue()} onChange={singleChange} />)

      }
    </div>
  );
});
Cascader.displayName = 'Cascader';


Cascader.originValueFormat = (value, props) => {
  return getDocumentInfo(value, props).then((res) => {
    if (props.childModelConfig) {
      let result = combineResultId(props, res as Array<any>);
      if (Array.isArray(result) && result?.length > 1) {
        return result.toString();
      } else {
        return result.toString()
      }
    }
    return res;
  });
};

// export default Cascader;
export default connect(
  Cascader,
  mapProps({}, (props) => {
    return { ...props };
  }),
);
